package com.iwdnb.gkgz.common.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.iwdnb.bmnf.common.utils.HttpClientUtils;
import com.iwdnb.gkgz.common.model.dto.StockAnalasysData;
import com.iwdnb.gkgz.common.model.dto.StockAnalasysData.ScoreData;
import com.iwdnb.gkgz.common.model.dto.StockDayData;
import com.iwdnb.gkgz.common.model.dto.StockMinuteData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN;

@Slf4j
public class StockUtils {

    private Double stockRange;

    //public static void getRealtimeData(String code) {
    //    //HttpClient client = HttpClient.newHttpClient();
    //    //HttpRequest request = HttpRequest.newBuilder(URI.create(""))
    //    //    .setHeader("Referer", "https://finance.sina.com.cn")
    //    //    .build();
    //    //HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    //    //String body = response.body();
    //    String url = "https://hq.sinajs.cn/list=" + code;
    //    String body = HttpClientUtils.get(url);
    //    //HttpHeaders headers = new HttpHeaders();
    //    //headers.setContentType(MediaType.APPLICATION_JSON);
    //    //headers.set("Referer", "https://finance.sina.com.cn");
    //    //
    //    //HttpEntity entity = new HttpEntity<>(headers);
    //    //
    //    //ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
    //    //String body = response.getBody().toString();
    //    String[] infoStrings = body.split("\"");
    //    String[] infoArray = infoStrings[1].split(",");
    //    String name = infoArray[0];
    //    double price = Double.valueOf(infoArray[3]);
    //    double price_pre = Double.valueOf(infoArray[2]);
    //    String date = infoArray[30];
    //    String time = infoArray[31];
    //    System.out.println(body);
    //    System.out.println(date);
    //}

    public static List<StockDayData> getHistoryDataByYear(String code, String year) {
        return getHistoryData(code, year + "-01-01", year + "-12-30");
    }

    /**
     * @param code
     * @return
     */
    public static List<StockMinuteData> queryHistoryMinuteData(String code, List<Integer> periods) {
        List<StockMinuteData> list = new ArrayList<>();
        for (Integer period : periods) {
            list.addAll(queryHistoryMinuteData(code, period));
        }
        return list;
    }

    /**
     * 获取5、10、30、60分钟JSON数据；day日期、open开盘价、high最高价、low最低价、close收盘价、volume成交量；向前复权的数据。
     * 注意，最多只能获取最近的1023个数据节点。
     * eq:http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData
     * .getKLineData?symbol=sz002095&scale=60&ma=no&datalen=1023
     *
     * @param code
     * @param period
     * @return
     */
    public static List<StockMinuteData> queryHistoryMinuteData(String code, int period) {
        String url = "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData"
            + ".getKLineData?symbol=%s&scale=%s&ma=no&datalen=1023";
        url = String.format(url, code, period);
        String body = HttpClientUtils.get(url);
        //HttpHeaders headers = new HttpHeaders();
        ////headers.setContentType(MediaType.APPLICATION_JSON);
        ////headers.set("Referer", "https://finance.sina.com.cn");
        //
        //HttpEntity entity = new HttpEntity<>(headers);
        //ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        //String body = response.getBody().toString();
        JSONArray jsonArray = JSON.parseArray(body);
        List<StockMinuteData> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            StockMinuteData data = new StockMinuteData();
            data.setCode(code);
            Date date = DateUtil.parseDateTime(jsonObject.getString("day"));
            data.setDate(DateUtil.formatDate(date));
            data.setMinute(DateUtil.formatTime(date));
            data.setPrice(jsonObject.getBigDecimal("close"));
            data.setTradeNum(jsonObject.getBigDecimal("volume"));
            list.add(data);
        }
        return list;

    }

    public static List<StockDayData> getHistoryData(String code, String beginDate, String endDate) {
        try {
            //新浪股票行情历史接口
            String url = "https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=%s,day,%s,%s,%s,qfq";
            Date begin = DateUtil.parseDate(beginDate);
            Date end = DateUtil.parseDate(endDate);
            long date = DateUtil.between(begin, end, DateUnit.DAY);
            url = String.format(url, code, beginDate, endDate, date + "");
            String body = HttpClientUtils.get(url);
            //HttpHeaders headers = new HttpHeaders();
            ////headers.setContentType(MediaType.APPLICATION_JSON);
            ////headers.set("Referer", "https://finance.sina.com.cn");
            //
            //HttpEntity entity = new HttpEntity<>(headers);
            //ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
            //String body = response.getBody().toString();
            JSONObject jsonObject = JSON.parseObject(body);
            if (!jsonObject.getString("code").equals("0")) {
                log.error("getHistoryData response error:" + body);
                return null;
            }
            JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONObject(code).getJSONArray("qfqday");
            List<StockDayData> stockDayDataList = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONArray data = jsonArray.getJSONArray(i);
                StockDayData stockDayData = new StockDayData();
                stockDayData.setCode(code);
                stockDayData.setDate(data.getString(0));
                stockDayData.setOpenPrice(new BigDecimal(data.getString(1)));
                stockDayData.setClosePrice(new BigDecimal(data.getString(2)));
                stockDayData.setMaxPrice(new BigDecimal(data.getString(3)));
                stockDayData.setMinPrice(new BigDecimal(data.getString(4)));
                //stockDayData.setTradeNum(data.getInteger(5));
                stockDayDataList.add(stockDayData);
            }
            //工作日下午3点以后,把当天的数据获取放进去
            Date now = new Date();
            String today = DateUtil.formatDate(now);
            String endTimeStr = today + " 15:00:00";
            Date endTime = DateUtil.parseDateTime(endTimeStr);
            int week = DateUtil.dayOfWeek(endTime);
            boolean workDay = week != 1 && week != 7;
            StockDayData lastData = stockDayDataList.get(stockDayDataList.size() - 1);
            if (workDay && endTime.before(now) && !lastData.getDate().equals(today)) {
                //stockDayDataList.add(getTodayStockData(code));
            }
            return stockDayDataList;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public static BigDecimal getAveragePrice(List<StockDayData> stockDayDataList) {
        BigDecimal price = new BigDecimal(0);
        for (StockDayData stockDayData : stockDayDataList) {
            price = price.add(stockDayData.getClosePrice());
        }
        return price.divide(new BigDecimal(stockDayDataList.size()), RoundingMode.CEILING).setScale(3,
            RoundingMode.HALF_UP);
    }

    public static StockDayData getTodayStockData(String code) {
        return getTodayStockData(Lists.newArrayList(code)).get(0);
    }

    /**
     * 获取今日实时数据
     *
     * @param codes
     * @return
     */
    public static List<StockDayData> getTodayStockData(List<String> codes) {
        String code = StringUtils.join(codes, ",");
        String url = "http://qt.gtimg.cn/q=%s";
        url = String.format(url, code);
        String body = HttpClientUtils.get(url);
        String[] list = body.split(";");
        List<StockDayData> stockDayDataList = new ArrayList<>();
        for (String content : list) {
            String[] array = content.split("~");
            if (content.length() < 10) {
                continue;
            }
            StockDayData stockDayData = new StockDayData();
            String datetime = array[30];
            datetime = DateUtil.formatDate(DateUtil.parse(datetime, PURE_DATETIME_PATTERN));
            stockDayData.setCode(array[0].split("=")[0].substring(2).replaceAll("_",""));
            stockDayData.setDate(datetime);
            stockDayData.setOpenPrice(new BigDecimal(array[5]));
            stockDayData.setClosePrice(new BigDecimal(array[3]));
            stockDayData.setMaxPrice(new BigDecimal(array[41]));
            stockDayData.setMinPrice(new BigDecimal(array[42]));
            //stockDayData.setTradeNum(new BigDecimal(array[3]));
            stockDayDataList.add(stockDayData);
        }
        return stockDayDataList;
    }

    public static List<StockMinuteData> getRealtimeMinuteData(String code) {
        String URL = "https://web.ifzq.gtimg.cn/appstock/app/minute/query?code=%s";
        String url = String.format(URL, code);
        String body = HttpClientUtils.postJSON(url, new JSONObject());
        //HttpHeaders headers = new HttpHeaders();
        //HttpEntity entity = new HttpEntity<>(headers);
        //headers.setContentType(MediaType.APPLICATION_JSON);
        //ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        //String body = response.getBody().toString();
        JSONObject jsonObject = JSON.parseObject(body);
        if (!jsonObject.getString("code").equals("0")) {
            log.error("getRealtimeMinuteData response error:" + body);
            return null;
        }
        JSONArray jsonArray = jsonObject.getJSONObject("data")
            .getJSONObject(code).getJSONObject("data")
            .getJSONArray("data");
        if (CollectionUtils.isEmpty(jsonArray)) {
            return null;
        }
        String date = DateUtil.formatDate(new Date());
        List<StockMinuteData> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            String content = jsonArray.getString(i);
            String[] array = content.split(" ");
            StockMinuteData data = new StockMinuteData();
            data.setDate(date);
            data.setMinute(array[0]);
            data.setPrice(new BigDecimal(array[1]));
            data.setTradeNum(new BigDecimal(array[2]));
            data.setTradeAmount(new BigDecimal(array[3]));
            list.add(data);
        }
        return list;
    }

    /**
     * 整体分析股票数据
     *
     * @param code
     * @param stockDayDataList
     * @return
     */
    public static StockAnalasysData analasysData(String code, List<StockDayData> stockDayDataList) {
        StockAnalasysData analasysData = new StockAnalasysData();
        analasysData.setCode(code);
        analasysData.setDays(stockDayDataList.size());
        ScoreData amplitudeCount = new ScoreData();
        ScoreData upData = new ScoreData();
        ScoreData downData = new ScoreData();
        analasysData.setAmplitudeCount(amplitudeCount);
        analasysData.setUpData(upData);
        analasysData.setDownData(downData);
        BigDecimal yesterdayPrice = stockDayDataList.get(0).getOpenPrice();
        BigDecimal yesterdayMaxPrice = stockDayDataList.get(0).getMaxPrice();
        BigDecimal yesterdayMinPrice = stockDayDataList.get(0).getMinPrice();
        int upCount = 0;
        int downCount = 0;
        int openUpDeviateYesterdayCount = 0;
        int openDownDeviateYesterdayCount = 0;
        int rangeDeviateYesterdayCount = 0;
        int maxCloseCount = 0;
        int minCloseCount = 0;
        int maxOpenCount = 0;
        int minOpenCount = 0;
        int index = 0;
        List<String> openUpDeviateDate = new ArrayList<>();
        List<String> openDownDeviateDate = new ArrayList<>();
        List<String> rangeDeviateDate = new ArrayList<>();
        for (StockDayData data : stockDayDataList) {
            //振幅
            int amplitude = data.getMaxPrice().subtract(data.getMinPrice()).multiply(new BigDecimal(100)).intValue();
            amplitudeCount.addScoreCount(amplitude);
            BigDecimal closePrice = data.getClosePrice();
            BigDecimal openPrice = data.getOpenPrice();

            //上涨
            if (closePrice.compareTo(yesterdayPrice) > 0) {
                int upScore = closePrice.subtract(yesterdayPrice).multiply(new BigDecimal(100)).intValue();
                upData.addScoreCount(upScore);
                upCount++;
            } else if (closePrice.compareTo(yesterdayPrice) < 0) {
                //下跌
                int downScore = yesterdayPrice.subtract(closePrice).multiply(new BigDecimal(100)).intValue();
                downData.addScoreCount(downScore);
                downCount++;

            }
            if (data.getMaxPrice().compareTo(openPrice) == 0) {
                maxOpenCount++;
            }
            if (data.getMaxPrice().compareTo(closePrice) == 0) {
                maxCloseCount++;
            }
            if (data.getMinPrice().compareTo(openPrice) == 0) {
                minOpenCount++;
            }
            if (data.getMinPrice().compareTo(closePrice) == 0) {
                minCloseCount++;
            }
            //偏离振幅
            if (openPrice.compareTo(yesterdayMaxPrice) > 0) {
                openUpDeviateYesterdayCount++;
                openUpDeviateDate.add(data.getDate());
            }
            if (openPrice.compareTo(yesterdayMinPrice) < 0) {
                openDownDeviateYesterdayCount++;
                openDownDeviateDate.add(data.getDate());
            }
            //振幅偏离
            if (data.getMinPrice().compareTo(yesterdayMaxPrice) > 0 || data.getMaxPrice().compareTo(yesterdayMinPrice)
                < 0) {
                rangeDeviateYesterdayCount++;
                rangeDeviateDate.add(data.getDate());
            }

            yesterdayPrice = closePrice;
            yesterdayMaxPrice = data.getMaxPrice();
            yesterdayMinPrice = data.getMinPrice();
            index++;
        }
        amplitudeCount.caculate();
        upData.caculate();
        downData.caculate();
        analasysData.setUpCount(upCount);
        analasysData.setDownCount(downCount);
        analasysData.setOpenUpDeviateYesterdayCount(openUpDeviateYesterdayCount);
        analasysData.setOpenDownDeviateYesterdayCount(openDownDeviateYesterdayCount);
        analasysData.setRangeDeviateYesterdayCount(rangeDeviateYesterdayCount);
        analasysData.setOpenUpDeviateDate(openUpDeviateDate);
        analasysData.setOpenDownDeviateDate(openDownDeviateDate);
        analasysData.setRangeDeviateDate(rangeDeviateDate);
        analasysData.setMaxOpenCount(maxOpenCount);
        analasysData.setMinOpenCount(minOpenCount);
        analasysData.setMaxCloseCount(maxCloseCount);
        analasysData.setMinCloseCount(minCloseCount);
        return analasysData;
    }

    public static void main(String[] args) {
        //StockUtils.getRealtimeData("sh600022");
        String code = "sh600022";//山东钢铁
        //code="sh600569";//安阳钢铁
        //code="sh600307";//酒钢宏兴
        List<StockDayData> stockDayDataList = StockUtils.getHistoryDataByYear(code, "2022");
        System.out.println(JSON.toJSONString(stockDayDataList));
        StockAnalasysData analasysData = StockUtils.analasysData(code, stockDayDataList);
        System.out.println("--------------------------------");
        System.out.println(JSON.toJSONString(analasysData));
        //获取历史分时数据
        List<StockMinuteData> list = StockUtils.queryHistoryMinuteData("sh600022", 60);
        System.out.println(JSON.toJSONString(list));
        StockDayData stockDayData = StockUtils.getTodayStockData("sh601005");
        StockDayData stockDayData2 = StockUtils.getTodayStockData("sh600569");
        System.out.println(JSON.toJSONString(stockDayData));
        System.out.println(JSON.toJSONString(stockDayData2));
    }
}

